// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stddef.h>

#include <sstream>

#include "base/logging.h"
#include "base/numerics/safe_math.h"
#include "media/gpu/ipc/common/media_param_traits.h"

namespace IPC {

void ParamTraits<media::BitstreamBuffer>::GetSize(base::PickleSizer* s,
    const param_type& p)
{
    GetParamSize(s, p.id());
    GetParamSize(s, static_cast<uint64_t>(p.size()));
    GetParamSize(s, static_cast<uint64_t>(p.offset()));
    GetParamSize(s, p.presentation_timestamp());
    GetParamSize(s, p.key_id());
    if (!p.key_id().empty()) {
        GetParamSize(s, p.iv());
        GetParamSize(s, p.subsamples());
    }
    GetParamSize(s, p.handle());
}

void ParamTraits<media::BitstreamBuffer>::Write(base::Pickle* m,
    const param_type& p)
{
    WriteParam(m, p.id());
    WriteParam(m, static_cast<uint64_t>(p.size()));
    DCHECK_GE(p.offset(), 0);
    WriteParam(m, static_cast<uint64_t>(p.offset()));
    WriteParam(m, p.presentation_timestamp());
    WriteParam(m, p.key_id());
    if (!p.key_id().empty()) {
        WriteParam(m, p.iv());
        WriteParam(m, p.subsamples());
    }
    WriteParam(m, p.handle());
}

bool ParamTraits<media::BitstreamBuffer>::Read(const base::Pickle* m,
    base::PickleIterator* iter,
    param_type* r)
{
    DCHECK(r);
    uint64_t size = 0;
    uint64_t offset = 0;
    if (!(ReadParam(m, iter, &r->id_) && ReadParam(m, iter, &size) && ReadParam(m, iter, &offset) && ReadParam(m, iter, &r->presentation_timestamp_) && ReadParam(m, iter, &r->key_id_)))
        return false;

    base::CheckedNumeric<size_t> checked_size(size);
    if (!checked_size.IsValid()) {
        DLOG(ERROR) << "Invalid size: " << size;
        return false;
    }
    r->size_ = checked_size.ValueOrDie();

    base::CheckedNumeric<off_t> checked_offset(offset);
    if (!checked_offset.IsValid()) {
        DLOG(ERROR) << "Invalid offset: " << offset;
        return false;
    }
    r->offset_ = checked_offset.ValueOrDie();

    if (!r->key_id_.empty()) {
        if (!(ReadParam(m, iter, &r->iv_) && ReadParam(m, iter, &r->subsamples_)))
            return false;
    }

    return ReadParam(m, iter, &r->handle_);
}

void ParamTraits<media::BitstreamBuffer>::Log(const param_type& p,
    std::string* l)
{
    std::ostringstream oss;
    oss << "id=" << p.id() << ", size=" << p.size() << ", presentation_timestamp="
        << p.presentation_timestamp().ToInternalValue();
    l->append(oss.str());
}

} // namespace IPC

// Generate param traits size methods.
#include "ipc/param_traits_size_macros.h"
namespace IPC {
#undef MEDIA_GPU_IPC_COMMON_MEDIA_PARAM_TRAITS_MACROS_H_
#include "media/gpu/ipc/common/media_param_traits_macros.h"
}

// Generate param traits write methods.
#include "ipc/param_traits_write_macros.h"
namespace IPC {
#undef MEDIA_GPU_IPC_COMMON_MEDIA_PARAM_TRAITS_MACROS_H_
#include "media/gpu/ipc/common/media_param_traits_macros.h"
} // namespace IPC

// Generate param traits read methods.
#include "ipc/param_traits_read_macros.h"
namespace IPC {
#undef MEDIA_GPU_IPC_COMMON_MEDIA_PARAM_TRAITS_MACROS_H_
#include "media/gpu/ipc/common/media_param_traits_macros.h"
} // namespace IPC

// Generate param traits log methods.
#include "ipc/param_traits_log_macros.h"
namespace IPC {
#undef MEDIA_GPU_IPC_COMMON_MEDIA_PARAM_TRAITS_MACROS_H_
#include "media/gpu/ipc/common/media_param_traits_macros.h"
} // namespace IPC
